package view;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Enumeration;

import javax.swing.AbstractButton;
import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;

import controller.Controller;
import controller.EventListener;

/**
 * 
 * This is the class for our GUI
 * 
 */
public class Gui extends JFrame {

	private JMenuBar menuBar;
	private JMenuItem menuItemFile;
	private JMenuItem menuItemExit;
	private JMenu menuFile;
	private JMenu menuHelp;
	private JPanel colorArea;
	private JPanel statisticArea;
	private JPanel colorChooseArea;
	private ArrayList<ArrayList<JPanel>> listStatistics;
	private ArrayList<ArrayList<JPanel>> listColorArea;
	private Color colorList[];
	private ButtonGroup buttonGroup;
	private Controller con;
	private JMenuItem menuItemManual;
	private InformationGui info;

	/**
	 * This is the constructor
	 */
	public Gui() {
		info = new InformationGui();
		info.createGui();
		info.setVisible(true);
	}

	/**
	 * function to create the gui
	 */
	public void createGui() {
		// set the size of the window
		this.setSize(500, 700);
		// set the title of the window
		this.setTitle("Super-Brain");
		this.setResizable(false);
		// set the layout of the GUI
		BorderLayout layoutGui = new BorderLayout();
		this.setLayout(layoutGui);
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);

		createMenuBar();
		createColorArea();
		createStatisticArea();
		createColorChooseArea();
		prepareFieldForTurn();

		// add the different parts of the gui to the main window
		this.add(colorArea, BorderLayout.WEST);
		this.add(statisticArea, BorderLayout.CENTER);
		this.add(colorChooseArea, BorderLayout.EAST);
		this.setVisible(true);
		this.pack();

	}

	/**
	 * function to create the menubar
	 */
	private void createMenuBar() {
		menuBar = new JMenuBar();
		menuBar.setPreferredSize(new Dimension(300, 25));
		menuFile = new JMenu("File");
		// add an item to the menu
		menuItemFile = new JMenuItem("Restart");
		// add an actionlistener to the item so that something cann happen
		menuItemFile.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				restart();
			}
		});

		menuItemExit = new JMenuItem("Exit");
		menuItemExit.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				System.exit(0);
			}
		});

		menuFile.add(menuItemFile);
		menuFile.add(menuItemExit);

		menuHelp = new JMenu("Help");
		menuItemManual = new JMenuItem("Manual");
		menuItemManual.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				// Create the help window
				info = new InformationGui();
				info.createGui();
				info.setVisible(true);

			}
		});

		menuHelp.add(menuItemManual);
		menuBar.add(menuFile);
		menuBar.add(menuHelp);
		this.add(menuBar, BorderLayout.NORTH);
		// create an Array for the guessed colors
		colorList = new Color[4];
	}

	/**
	 * create the part of the window whrer the user can choose the color he want
	 * to guess
	 */
	private void createColorChooseArea() {
		// create a panel and set the size al well as the layout
		colorChooseArea = new JPanel();
		colorChooseArea.setPreferredSize(new Dimension(100, 750));
		colorChooseArea.setLayout(new GridLayout(8, 1));

		// add a label for information
		JLabel label = new JLabel();
		label.setText("Choose a color:");

		// add a radiobutton for each color
		JRadioButton radioButtonBlack = new JRadioButton("Black");
		JRadioButton radioButtonBlue = new JRadioButton("Blue");
		JRadioButton radioButtonPurple = new JRadioButton("Purple");
		JRadioButton radioButtonYellow = new JRadioButton("Yellow");
		JRadioButton radioButtonGreen = new JRadioButton("Green");
		JRadioButton radioButtonBrown = new JRadioButton("Brown");

		// add the radiobuttons to a buttongroup so that it is just possible to
		// select one
		buttonGroup = new ButtonGroup();
		buttonGroup.add(radioButtonBrown);
		buttonGroup.add(radioButtonGreen);
		buttonGroup.add(radioButtonYellow);
		buttonGroup.add(radioButtonPurple);
		buttonGroup.add(radioButtonBlue);
		buttonGroup.add(radioButtonBlack);

		// add the radiobuttons to the panel on the frame
		colorChooseArea.add(label);
		colorChooseArea.add(radioButtonBlack);
		colorChooseArea.add(radioButtonBrown);
		colorChooseArea.add(radioButtonGreen);
		colorChooseArea.add(radioButtonYellow);
		colorChooseArea.add(radioButtonPurple);
		colorChooseArea.add(radioButtonBlue);

	}

	/**
	 * create the part of the window where the computer gives the hints for the
	 * game
	 */
	private void createStatisticArea() {
		// create a new panel, set the size, background color and layout
		statisticArea = new JPanel();
		statisticArea.setPreferredSize(new Dimension(100, 750));
		statisticArea.setLayout(new FlowLayout());
		statisticArea.setBackground(Color.BLACK);

		// create a list where we save all our panel for the hints
		listStatistics = new ArrayList<ArrayList<JPanel>>();

		// create the objects
		for (int i = 1; i <= 10; i++) {
			// create ten rows each with 4 circles, set their size and add them
			// to the layout and panel
			JPanel row = new JPanel();
			row.setPreferredSize(new Dimension(100, 70));
			row.setBackground(Color.YELLOW);

			row.setLayout(new GridLayout(2, 2, 40, 20));
			ArrayList<JPanel> circleList = new ArrayList<JPanel>();
			for (int j = 0; j < 4; j++) {

				JPanel circle = new Circle();
				circle.setPreferredSize(new Dimension(5, 5));
				circle.setBackground(Color.WHITE);
				row.add(circle);
				circleList.add(circle);
			}
			// save them in our list
			listStatistics.add(circleList);
			statisticArea.add(row);
		}
	}

	/**
	 * create the part of the window where the user can interact with the
	 * programm to guess the colors
	 */
	private void createColorArea() {
		// same as above
		colorArea = new JPanel();
		colorArea.setPreferredSize(new Dimension(300, 750));
		colorArea.setBackground(Color.BLACK);
		listColorArea = new ArrayList<ArrayList<JPanel>>();

		for (int i = 1; i <= 10; i++) {
			JPanel row = new JPanel();
			row.setPreferredSize(new Dimension(300, 70));
			row.setBackground(Color.white);

			// create a label so that the user knows in which round he is
			JLabel label = new JLabel();
			label.setText("Round " + Integer.toString(11 - i) + ":");
			row.add(label);
			ArrayList<JPanel> listCircles = new ArrayList<JPanel>();

			for (int j = 1; j <= 4; j++) {
				JPanel draw = new Circle();
				draw.setPreferredSize(new Dimension(50, 50));
				// add a mouslistener to each circle that reacts if you press
				// the mouse on it
				draw.addMouseListener(new EventListener() {
					@Override
					public void mousePressed(MouseEvent e) {
						// get the panel that was clicked
						JPanel panel = (JPanel) e.getSource();
						// Get the position of the guess so that you know which
						// of the 4 cirlces is clicked
						int positionOfGuess = 0;
						// search through the list to find the panel which is
						// like the clicked panel
						for (int i = 0; i < listColorArea.get(
								10 - con.getRoundNumber()).size(); i++) {
							if (panel.equals(listColorArea.get(
									10 - con.getRoundNumber()).get(i))) {
								positionOfGuess = i;
							}
						}
						// if the panel is focusable go on
						if (panel.isFocusable() == true) {
							// get the grafic on the panel which is the cirle
							Graphics2D g2d = (Graphics2D) panel.getGraphics();
							JRadioButton radioButton;
							try {
								// get the selected radiobutton where the player
								// has choosen the color
								radioButton = (JRadioButton) getSelectedButton(buttonGroup);
								// if the radiobtton is enable so that you can't
								// use the same color twice
								if (radioButton.isEnabled() == true) {
									// get the color from the radiobutoon and
									// create a new cricle with this color
									g2d.setColor(con.getRGB(radioButton
											.getText()));
									g2d.fillOval(0, 0, panel.getWidth(),
											panel.getHeight());
									// enable the radiobutton
									radioButton.setEnabled(false);
									g2d.setColor(Color.red);
									// add the guesscolor to the list of the
									// gussedcolors
									colorList[positionOfGuess] = con
											.getRGB(radioButton.getText());
									panel.setFocusable(false);
									// if no next ove is allowed in this round
									// send the list of gussed colors o the
									// controller
									if (con.nextMove() == false) {
										// send the colors
										boolean won = con.saveColors(colorList);
										showHints();
										// if the player hasn't won yet go to
										// the next round, prepare the filed and
										// creat a new list for the colors
										if (won == false) {
											con.nextRound();
											prepareFieldForTurn();
											colorList = new Color[4];
										}
									}
								}
								//if the player made a mistake show an errorpopup
							} catch (NullPointerException e2) {
								JOptionPane.showMessageDialog(null,
										"Please choose a color", "Error",
										JOptionPane.ERROR_MESSAGE);
							}
						}
					}
				});
				//add the circle and panel to the list
				row.add(draw);
				listCircles.add(draw);
			}
			listColorArea.add(listCircles);
			colorArea.add(row);
		}
	}

	/**
	 * function to show the hints
	 */
	protected void showHints() {
		//get the number of right colors and places from the controller
		int rightColor = con.getNumberRightColor();
		int rightPlace = con.getNumberRightPlace();
		//create circles for the right color in the same row as the palyer has guessed
		for (int i = 0; i < rightColor; i++) {
			JPanel panel = listStatistics.get(10 - con.getRoundNumber()).get(i);
			Graphics2D g2d = (Graphics2D) panel.getGraphics();
			g2d.setColor(Color.WHITE);
			g2d.fillOval(0, 0, panel.getWidth(), panel.getHeight());
		}
		//create circles for the right place in the same row as the palyer has guessed
		for (int i = rightColor; i < rightColor + rightPlace; i++) {
			JPanel panel = listStatistics.get(10 - con.getRoundNumber()).get(i);
			Graphics2D g2d = (Graphics2D) panel.getGraphics();
			g2d.setColor(Color.RED);
			g2d.fillOval(0, 0, panel.getWidth(), panel.getHeight());
		}

	}

	/**
	 * prepare the field for the next round. Set the next row focusable and set all other row nonfocusable
	 */
	public void prepareFieldForTurn() {
		int roundnumber = con.getRoundNumber();
		for (int i = 0; i < listColorArea.size() - 1; i++) {
			for (JPanel panel : listColorArea.get(i)) {
				panel.setFocusable(false);
			}
		}
		for (JPanel panel : listColorArea.get(10 - roundnumber)) {
			panel.setFocusable(true);
		}
		// Enable all the radio buttons again so that every color could be choosen again		
		for (Enumeration<AbstractButton> buttons = buttonGroup.getElements(); buttons
				.hasMoreElements();) {
			JRadioButton radioButton = (JRadioButton) buttons.nextElement();
			radioButton.setEnabled(true);
		}
	}

	/**
	 * Source: http://stackoverflow.com/questions/201287/how-do-i-get-which-
	 * jradiobutton -is-selected-from-a-buttongroup
	 * gives us back the selected radiobutton from a buttongroup
	 */
	public AbstractButton getSelectedButton(ButtonGroup buttonGroup) {
		for (Enumeration<AbstractButton> buttons = buttonGroup.getElements(); buttons
				.hasMoreElements();) {
			AbstractButton button = buttons.nextElement();

			if (button.isSelected()) {
				return button;
			}
		}

		return null;
	}
	/**
	 * function to restart the programm
	 */
	public void restart() {
		//update the circles in the Colorarea and color them all gray
		for (ArrayList<JPanel> listPanel : listColorArea) {
			for (JPanel jPanel : listPanel) {
				Graphics2D g2d = (Graphics2D) jPanel.getGraphics();
				g2d.setColor(Color.GRAY);
				g2d.fillOval(0, 0, jPanel.getWidth(), jPanel.getHeight());
				jPanel.setFocusable(false);
			}
		}
		//update the circles in the statisticarea and color them all gray
		for (ArrayList<JPanel> listPanel : listStatistics) {
			for (JPanel jPanel : listPanel) {
				Graphics2D g2d = (Graphics2D) jPanel.getGraphics();
				g2d.setColor(Color.GRAY);
				g2d.fillOval(0, 0, jPanel.getWidth(), jPanel.getHeight());
			}
		}
		//reset the programm in the controller
		con.resetProgram();
		prepareFieldForTurn();
	}

	/**
	 * function to create a popup window that asks if you want to pay again
	 */
	public void playAgain(boolean won) {
		String message;
		if (won)
			message = "Congratulations, you have won! Well done!";
		else
			message = "I'm sorry. Next time you will win!";
		// create the popup window with the standart template of java
		int decision = JOptionPane.showOptionDialog(null,
				"Do you want to play again?", message,
				JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null,
				null, null);
		// if decision was yes
		if (decision == 0)
			restart();
	}
	/**
	 * let the gui know the controller
	 */
	public void setController(Controller controller) {
		this.con = controller;
	}
}
